/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_accept.c                                       */
/*  NOTE      =                                                    */
/*  DATE      = 2014/09/26 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "frcomm.h"
#include "frstr.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../comm/ora_comm.h"
#include "../ora_core.h"
#include "ora_accept.h"
#include "../ttc/ora_mar_engine.h"
#include "../comm/ora_util.h"

/*******************************************************************************
*  FUNC     :  解析accept包，设置TNS版本号、largeSDUFlag、sdu
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_accept_unpack(Conntrack *p_st_conn
                    , L7session_ora *p_st_sess
                    , L7_ora_packet *p_st_ora_packet)
{
    unsigned short us_tns_version;                  // tns version
    unsigned short us_sdu;                          // session data unit size
    uint64_t uint64_sdu;                            // session data unit size
    unsigned short us_srv_value1inhardware;         // value of 1 in hardware

    APM_ORA_SET_PHASE_P_ACCEPT(p_st_sess->ull_bits_phase_progress);

    bytebuff_setPosition(p_st_ora_packet->p_st_packet, APM_ORA_PKT_HEADER_LEN);      // 跳过包头
    if (bytebuff_get_short(p_st_ora_packet->p_st_packet, 2, &us_tns_version, BYTE_BIG_ENDIAN) != FR_SUCC)
        goto error;
    p_st_sess->s_tns_version = us_tns_version;

    if (bytebuff_get_short(p_st_ora_packet->p_st_packet, 2, &us_tns_version, BYTE_BIG_ENDIAN) != FR_SUCC)
        goto error;
    p_st_sess->s_negotiated_options = us_tns_version;

    if (bytebuff_get_short(p_st_ora_packet->p_st_packet, 2, &us_sdu, BYTE_BIG_ENDIAN) != FR_SUCC)
        goto error;
    p_st_sess->s_sdu = us_sdu;

    if (ora_mar_skip(p_st_ora_packet, 2) != FR_SUCC)
        goto error;
    if (bytebuff_get_short(p_st_ora_packet->p_st_packet, 2, &us_srv_value1inhardware, BYTE_BIG_ENDIAN) != FR_SUCC)
        goto error;
    p_st_sess->i_srv_is_bigendian = us_srv_value1inhardware == 0x0001 ? FR_YES : FR_NO;
    if (p_st_sess->i_use_oci == FR_YES)
    {
        if (p_st_sess->i_srv_is_bigendian == FR_YES)
            p_st_sess->i_use_special_field = p_st_sess->i_cli_is_bigendian == FR_YES ? FR_YES : FR_NO;
        else
            p_st_sess->i_use_special_field = FR_YES;
    }
    else
        p_st_sess->i_use_special_field = FR_NO;
    ORA_PRINT_PARAM("i_use_special_field:[%s]\n", FR_YESNO2STR(p_st_sess->i_use_special_field));

    if (p_st_sess->s_tns_version >= 315)
    {
        if (ora_mar_skip(p_st_ora_packet, 14) != FR_SUCC)
            goto error;
        if (bytebuff_get_long(p_st_ora_packet->p_st_packet, 4, &uint64_sdu, BYTE_BIG_ENDIAN) != FR_SUCC)
            goto error;
        p_st_sess->s_sdu = (short) uint64_sdu;

        ora_sess_set_large_sdu_flag(p_st_sess, 1);
    }

    ORA_PRINT_DBG("s_tns_version:[%d]\n", p_st_sess->s_tns_version);
    ORA_PRINT_DBG("Session Data Unit Size:[%d]\n", p_st_sess->s_sdu);

    return FR_SUCC;
error:
    return FR_FAIL;
}
